package enhance.plus.util;

import common.core.util.CommonUtil;
import lombok.Data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * @author liubo
 * @created 2020-07-06 14:49
 */
@Data
public class Criterion {

    private List<Criterion> criterions;

    /**
     * 操作符
     */
    private String operator;
    /**
     * 字段
     */
    private String column;
    /**
     * 值
     */
    private Object value;
    /**
     * 第二个值
     */
    private Object secondValue;

    /**
     * column = value
     */
    public Criterion eq(String column, Object value){
        return this.eq(true, column, value);
    }
    /**
     * column = value
     */
    public Criterion eq(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.EQ, value, null);
        return this;
    }

    /**
     * column != value
     */
    public Criterion ne(String column, Object value){
        return this.ne(true, column, value);
    }
    /**
     * column != value
     */
    public Criterion ne(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.NE, value, null);
        return this;
    }

    /**
     * exists(existsSql)
     */
    public Criterion exists(String existsSql){
        return this.exists(true, existsSql);
    }
    /**
     * exists(existsSql)
     */
    public Criterion exists(boolean isTrue ,String notExistsSql){
        this.initCriterions(isTrue,column,QueryUtil.NOT_EXISTS, value, null);
        return this;
    }

    /**
     * not exists(notExistsSql)
     */
    public Criterion notExists(String notExistsSql){
        return this.notExists(true, notExistsSql);
    }
    /**
     * not exists(notExistsSql)
     */
    public Criterion notExists(boolean isTrue ,String notExistsSql){
        this.initCriterions(isTrue,column,QueryUtil.NOT_EXISTS, value, null);
        return this;
    }

    /**
     * column like '%value%'
     */
    public Criterion like(String column, Object value){
        return this.like(true, column, value);
    }
    /**
     * column like '%value%'
     */
    public Criterion like(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.LIKE, value, null);
        return this;
    }
    /**
     * column not like '%value%'
     */
    public Criterion notLike(String column, Object value){
        return this.notLike(true, column, value);
    }
    /**
     * column not like '%value%'
     */
    public Criterion notLike(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.NOT_LIKE, value, null);
        return this;
    }

    /**
     * column like '%value'
     */
    public Criterion likeLeft(String column, Object value){
        return this.likeLeft(true, column, value);
    }
    /**
     * column like '%value'
     */
    public Criterion likeLeft(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.LIKE_LEFT, value, null);
        return this;
    }

    /**
     * column not like '%value'
     */
    public Criterion notLikeLeft(String column, Object value){
        return this.notLikeLeft(true, column, value);
    }
    /**
     * column not like '%value'
     */
    public Criterion notLikeLeft(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.NOT_LIKE_LEFT, value, null);
        return this;
    }

    /**
     * column like 'value%'
     */
    public Criterion likeRight(String column, Object value){
        return this.likeRight(true, column, value);
    }
    /**
     * column like 'value%'
     */
    public Criterion likeRight(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.LIKE_RIGHT, value, null);
        return this;
    }

    /**
     * column not like 'value%'
     */
    public Criterion notLikeRight(String column, Object value){
        return this.notLikeRight(true, column, value);
    }
    /**
     * column not like 'value%'
     */
    public Criterion notLikeRight(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.NOT_LIKE_RIGHT, value, null);
        return this;
    }

    /**
     * column in(coll)
     */
    public Criterion inByCollection(String column, Collection<?> coll) {
        return this.inByCollection(true, column, coll);
    }

    /**
     * column in(coll)
     */
    public Criterion inByCollection(boolean isTrue , String column, Collection<?> value){
        this.initCriterions(isTrue,column,QueryUtil.IN, value, null);
        return this;
    }
    /**
     * column in(values)
     */
    public Criterion inByArray(String column, Object... values) {
        return this.inByArray(true, column, values);
    }
    /**
     * column in(values)
     */
    public Criterion inByArray(boolean isTrue , String column, Object... values){
        this.inByCollection(isTrue, column, Arrays.asList(values));
        return this;
    }
    /**
     * column in(sql)
     */
    public Criterion inBySql(String column, String sql) {
        return this.inBySql(true, column, sql);
    }
    /**
     * column in(sql)
     */
    public Criterion inBySql(boolean isTrue , String column, String sql ){
        this.initCriterions(isTrue,column,QueryUtil.IN, value, null);
        return this;
    }

    /**
     * column not in(coll)
     */
    public Criterion notInByCollection(String column, Collection<?> coll) {
        return this.notInByCollection(true, column, coll);
    }
    /**
     * column not in(coll)
     */
    public Criterion notInByCollection(boolean isTrue , String column, Collection<?> coll){
        this.initCriterions(isTrue,column,QueryUtil.NOT_IN, coll, null);
        return this;
    }
    /**
     * column not in(values)
     */
    public Criterion notInByArray(String column, Object... values) {
        return this.notInByArray(true, column, values);
    }
    /**
     * column not in(values)
     */
    public Criterion notInByArray(boolean isTrue , String column, Object... values){
        this.notInByCollection(isTrue, column, Arrays.asList(values));
        return this;
    }
    /**
     * column not in(sql)
     */
    public Criterion notInBySql(String column, String sql) {
        return this.notInBySql(true, column, sql);
    }
    /**
     * column not in(sql)
     */
    public Criterion notInBySql(boolean isTrue , String column, String sql ){
        this.initCriterions(isTrue,column,QueryUtil.NOT_IN, value, null);
        return this;
    }

    /**
     * column is null
     */
    public Criterion isNull(String column){
        return this.isNull(true, column);
    }
    /**
     * column is null
     */
    public Criterion isNull(boolean isTrue ,String column){
        this.initCriterions(isTrue,column,QueryUtil.IS_NULL, value, null);
        return this;
    }

    /**
     * column is not null
     */
    public Criterion isNotNull(String column){
        return this.isNotNull(true, column);
    }
    /**
     * column is not null
     */
    public Criterion isNotNull(boolean isTrue ,String column){
        this.initCriterions(isTrue,column,QueryUtil.IS_NOT_NULL, value, null);
        return this;
    }

    /**
     * column <= value
     */
    public Criterion le(String column, Object value){
        return this.le(true, column, value);
    }
    /**
     * column <= value
     */
    public Criterion le(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.LE, value, null);
        return this;
    }

    /**
     * column >= value
     */
    public Criterion ge(String column, Object value){
        return this.ge(true, column, value);
    }
    /**
     * column >= value
     */
    public Criterion ge(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.GE, value, null);
        return this;
    }

    /**
     * column < value
     */
    public Criterion lt(String column, Object value){
        return this.lt(true, column, value);
    }
    /**
     * column < value
     */
    public Criterion lt(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.LT, value, null);
        return this;
    }
    /**
     * column > value
     */
    public Criterion gt(String column, Object value){
        return this.gt(true, column, value);
    }
    /**
     * column > value
     */
    public Criterion gt(boolean isTrue ,String column, Object value){
        this.initCriterions(isTrue,column,QueryUtil.GT, value, null);
        return this;
    }

    /**
     * column between value and secondValue
     */
    public Criterion betweenAnd(String column, Object value,Object secondValue){
        return this.betweenAnd(true, column, value,secondValue);
    }
    public Criterion betweenAnd(boolean isTrue ,String column, Object value,Object secondValue){
        this.initCriterions(isTrue,column,QueryUtil.BETWEEN_AND, value, secondValue);
        return this;
    }

    private void initCriterions(boolean isTrue, String column,String operator,
                                Object value,Object secondValue){
        if(isTrue){
            if(CommonUtil.isEmpty(criterions)){
                this.criterions = new ArrayList<>();
            }
            Criterion criterion = new Criterion();

            criterion.setColumn(column);
            criterion.setOperator(operator);
            criterion.setValue(value);
            criterion.setSecondValue(secondValue);
            this.criterions.add(criterion);
        }
    }

}
